package com.vecspace.statistics.counter;

import java.util.List;
import java.util.TreeSet;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;

/**记录度量值最大的前N个记录
 * @author: wanghua
 */
public class TopNContainer {
	
	public TopNContainer(int topN) {
		if(topN >= 1) {
			this.topN = topN;
		}
	}
	
	private int topN = 10;
	private double minValue = Double.MAX_VALUE;//最小的metric
	private double maxValue = Double.MIN_VALUE;//最大的metric
	private TreeSet<SortableItem> treeset = new TreeSet<>();
	ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	
	public void put(double metric, Object item) {
		
		lock.writeLock().lock();
		try {
			if(metric < minValue && treeset.size() == topN) {//如果队列中已经有topN个对象，而当前对象的度量值小于最小的值，则忽略它。
				return;
			}			
			SortableItem sortitem = new SortableItem(metric, item);
			treeset.add(sortitem);
			if(treeset.size() > topN) {
				treeset.pollLast();
			}
			
			if(metric < minValue) {
				minValue = metric;
			}
			if(metric > maxValue) {
				maxValue = metric;
			}
		}finally {
			lock.writeLock().unlock();
		}
	}
	
	public List<Object> getTopNItems(){
		lock.readLock().lock();
		try {
			List<Object> list = treeset.stream().map(sortitem -> sortitem.item).collect(Collectors.toList());
			return list;
		}finally {
			lock.readLock().unlock();
		}
	}
	
	public static void main(String[] args) {
		TopNContainer c = new TopNContainer(10);
		c.put(1 , 1 );
		c.put(2 , 2 );
		c.put(3 , 3 );
		c.put(4 , 4 );
		c.put(5 , 5 );
		c.put(6 , 6 );
		c.put(7 , 7 );
		c.put(8 , 8 );
		c.put(9 , 9 );
		c.put(10, 10.1);
		c.put(11, 11);
		c.put(12, 12);
		c.put(21, 21);
		c.put(22, 22);
		c.put(23, 23);
		c.put(24, 24);
		c.put(25, 25);
		c.put(26, 26);
		c.put(27, 27);
		c.put(28, 28);
		c.put(29, 29);
		c.put(30, 30.1);
		c.put(30, 30.2);
		c.put(10, 10.2);
		c.put(13, 13);
		c.put(14, 14);
		c.put(15, 15);
		c.put(16, 16);
		c.put(17, 17);
		c.put(18, 18);
		c.put(19, 19);
		c.put(20, 20);
		
		c.getTopNItems().stream().forEach(item -> System.out.println(item));
	}
	
	
	class SortableItem implements Comparable<SortableItem>{
		
		public SortableItem() {
			
		}
		
		public SortableItem(double metric, Object item) {
			this.metric = metric;
			this.item = item;
		}

		private double metric;
		private Object item;
		public double getMetric() {
			return metric;
		}
		public void setMetric(double metric) {
			this.metric = metric;
		}
		public Object getItem() {
			return item;
		}
		public void setItem(Object item) {
			this.item = item;
		}

		@Override
		public int compareTo(SortableItem o) {
			if(metric == o.metric)return 1;//重要： 不能返回0，返回0表示两个对象在TreeSet中只保留一个。返回1表示两个对象在TreeSet中都保留，并且保留加入时的顺序
			else if(metric > o.metric)return -1;
			else return 1;
		}
		
	}
}

